package rothag.views.gamestep.develop;

import java.awt.*;
import java.awt.datatransfer.StringSelection;
import java.awt.dnd.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import rothag.controller.MainController;
import rothag.graphics.*;
import rothag.models.developpement.*;
import rothag.views.*;
import rothag.views.gamestep.GameStepJPanelBase;
import rothag.graphics.outlookbar.JOutlookBar;
import rothag.models.ressources.*;

/**
 *
 * @author Gaetan, François, Gulian
 * 
 */
public class DeveloppementJPanel extends GameStepJPanelBase implements ActionListener, DragSourceListener, DragGestureListener, ListSelectionListener {

    private ArrayList<Developpement> listeDevJoueur;
    private ArrayList<Class> listeRessourceSel;
    private Developpement selectedDeveloppement;
    private final DragSource ds;
    private StringSelection transferable;
    private JButtonBase etapeSuivante;
    private JTextArea descriptionText;
    private JList listLess;
    private JList listTop;
    private JList listMid;
    private JLabel bois;
    private JLabel pierre;
    private JLabel tissu;
    private JLabel poterie;
    private JLabel ferDeLance;
    private VendreJToggleButton boisButton;
    private VendreJToggleButton pierreButton;
    private VendreJToggleButton tissuButton;
    private VendreJToggleButton poterieButton;
    private VendreJToggleButton ferDeLanceButton;
    private JOutlookBar joutLook;
    private JButtonBase nourriturePlus;
    private JButtonBase nourritureMoins;
    private JLabel nourritureGrenier;
    private JLabel labelGrenier;
    private JLabel nbPieceTotal;
    private int nbNourritureDispo;
    private int nbPieceDispo;
    private int nbPieceSel;
    private int nbBois;
    private int nbPierre;
    private int nbPoterie;
    private int nbTissu;
    private int nbFerDeLance;
    private JList listeDropTarget;

    public DeveloppementJPanel(MainController controller, JList listeDropTarget) {
        super(controller);
        this.listeDropTarget = listeDropTarget;

        // Bouton étape suivante
        etapeSuivante = new JButtonBase("Etape suivante");
        etapeSuivante.setBounds(550, GraphicsParameters.smallFrameTopY + 60, 120, 40);
        etapeSuivante.addActionListener(this);
        add(etapeSuivante);

        // Texte
        JLabel label = new JLabel();
        label.setFont(GraphicsHelper.getFont(13, null));
        label.setForeground(Color.white);
        label.setBounds(100, 45, 300, 20);
        label.setText("Développements (triés par coût) :");
        add(label);

        label = new JLabel();
        label.setFont(GraphicsHelper.getFont(13, null));
        label.setForeground(Color.white);
        label.setBounds(470, 45, 300, 20);
        label.setText("Vente de ressources :");
        add(label);

        label = new JLabel();
        label.setFont(GraphicsHelper.getFont(13, null));
        label.setForeground(Color.white);
        label.setBounds(45, GraphicsParameters.bigFrameBottomY - 65, 340, 80);
        label.setText("<html>Pour acheter un developpement, glisser le devellopement choisi vers vos developpements dans la partie gauche ci-contre.</html>");
        add(label);

        label = new JLabel();
        label.setFont(GraphicsHelper.getFont(13, null));
        label.setForeground(Color.white);
        label.setBounds(45, GraphicsParameters.smallFrameTopY, 500, hauteur - GraphicsParameters.smallFrameTopY - 40);

        StringBuilder text = new StringBuilder("<html>Dans cette étape, vous pouvez acheter un développement (un seul par tour).<br>");
        text.append("Pour cela, utilisez vos pièces et/ou transformer vos ressources en pièces (tout surplus sera perdu).<br>");
        text.append("Si pouvez possédez le développement Grenier, vous avez aussi le possibilité de vendre de le nourriture :");
        text.append(" 1 nourriture contre 6 pièces (tout surplus sera perdu).</html>");

        label.setText(text.toString());
        add(label);

        // Text Area pour accueillir la description des developpements
        descriptionText = new JTextArea();
        descriptionText.setFont(GraphicsHelper.getFont(13, null));
        descriptionText.setForeground(Color.black);
        descriptionText.setBackground(Color.white);
        descriptionText.setLineWrap(true);
        descriptionText.setWrapStyleWord(true);

        JScrollPane scrollPane = new JScrollPane(descriptionText);
        scrollPane.setBackground(new Color(0, 0, 0, 0));
        scrollPane.setHorizontalScrollBar(null);
        scrollPane.setBounds(45, GraphicsParameters.bigFrameBottomY - 130, 340, 80);
        add(scrollPane);

        // Liste pour contenir les développements
        listLess = new JList();
        listLess.addListSelectionListener(this);
        listLess.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        listLess.setBorder(null);
        listMid = new JList();
        listMid.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        listMid.addListSelectionListener(this);
        listMid.setBorder(null);
        listTop = new JList();
        listTop.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        listTop.addListSelectionListener(this);
        listTop.setBorder(null);

        // Activation du Drag And Drop
        listLess.setDragEnabled(true);
        listTop.setDragEnabled(true);
        listMid.setDragEnabled(true);

        // Drag And Drop
        ds = new DragSource();
        DragGestureRecognizer dgr = ds.createDefaultDragGestureRecognizer(listLess, DnDConstants.ACTION_COPY, this);
        dgr = ds.createDefaultDragGestureRecognizer(listMid, DnDConstants.ACTION_COPY, this);
        dgr = ds.createDefaultDragGestureRecognizer(listTop, DnDConstants.ACTION_COPY, this);

        listeDropTarget.setTransferHandler(new ListTransferHandler(this));

        // ScrollPane pour accuellir les listes de développement
        JScrollPane jScrollTop = new JScrollPane(listTop);
        JScrollPane jScrollMid = new JScrollPane(listMid);
        JScrollPane jScrollLess = new JScrollPane(listLess);

        // Outlook bar
        joutLook = new JOutlookBar();
        joutLook.addTab("Développements Bronze", jScrollLess);
        joutLook.addTab("Développements Argent", jScrollMid);
        joutLook.addTab("Développements Or", jScrollTop);
        joutLook.setBounds(100, 70, 200, 210);
        add(joutLook);

        // Ajout des images des ressources
        int x = largeur / 2 + 50;
        int y = 70;
        int espace = 5;

        ImageIcon img = GraphicsHelper.getImageIcon(GraphicsParameters.pathImgBois, this);
        if (img.getIconHeight() == -1) {
            GraphicsHelper.afficherErreur("Erreur", "Erreur lors de l'ouverture du fichier image : " + GraphicsParameters.pathImgBois, this).setVisible(true);
            System.exit(1);
        }
        label = new JLabel(img);
        label.setBounds(x, y, img.getIconWidth(), img.getIconHeight());
        add(label);

        y += espace + img.getIconHeight();

        img = GraphicsHelper.getImageIcon(GraphicsParameters.pathImgPierre, this);
        if (img.getIconHeight() == -1) {
            GraphicsHelper.afficherErreur("Erreur", "Erreur lors de l'ouverture du fichier image : " + GraphicsParameters.pathImgPierre, this).setVisible(true);
            System.exit(1);
        }
        label = new JLabel(img);
        label.setBounds(x, y, img.getIconWidth(), img.getIconHeight());
        add(label);

        y += espace + img.getIconHeight();

        img = GraphicsHelper.getImageIcon(GraphicsParameters.pathImgPoterie, this);
        if (img.getIconHeight() == -1) {
            GraphicsHelper.afficherErreur("Erreur", "Erreur lors de l'ouverture du fichier image : " + GraphicsParameters.pathImgPoterie, this).setVisible(true);
            System.exit(1);
        }
        label = new JLabel(img);
        label.setBounds(x, y, img.getIconWidth(), img.getIconHeight());
        add(label);

        y += espace + img.getIconHeight();

        img = GraphicsHelper.getImageIcon(GraphicsParameters.pathImgTissu, this);
        if (img.getIconHeight() == -1) {
            GraphicsHelper.afficherErreur("Erreur", "Erreur lors de l'ouverture du fichier image : " + GraphicsParameters.pathImgTissu, this).setVisible(true);
            System.exit(1);
        }
        label = new JLabel(img);
        label.setBounds(x, y, img.getIconWidth(), img.getIconHeight());
        add(label);

        y += espace + img.getIconHeight();

        img = GraphicsHelper.getImageIcon(GraphicsParameters.pathImgFerDeLance, this);
        if (img.getIconHeight() == -1) {
            GraphicsHelper.afficherErreur("Erreur", "Erreur lors de l'ouverture du fichier image : " + GraphicsParameters.pathImgFerDeLance, this).setVisible(true);
            System.exit(1);
        }
        label = new JLabel(img);
        label.setBounds(x, y, img.getIconWidth(), img.getIconHeight());
        add(label);

        x = largeur / 2 + 60 + espace + img.getIconWidth();
        y = 70;

        // ajout des labels des ressources
        int hauteurLabel = img.getIconHeight();
        int largeurLabel = 140;
        bois = new JLabel("Gains : 0 pièce");
        bois.setForeground(Color.white);
        bois.setBounds(x, y, largeurLabel, hauteurLabel);
        add(bois);

        y += espace + img.getIconHeight();

        pierre = new JLabel("Gains : 0 pièce");
        pierre.setForeground(Color.white);
        pierre.setBounds(x, y, largeurLabel, hauteurLabel);
        add(pierre);

        y += espace + hauteurLabel;

        poterie = new JLabel("Gains : 0 pièce");
        poterie.setForeground(Color.white);
        poterie.setBounds(x, y, largeurLabel, hauteurLabel);
        add(poterie);

        y += espace + hauteurLabel;

        tissu = new JLabel("Gains : 0 pièce");
        tissu.setForeground(Color.white);
        tissu.setBounds(x, y, largeurLabel, hauteurLabel);
        add(tissu);

        y += espace + hauteurLabel;

        ferDeLance = new JLabel("Gains : 0 pièce");
        ferDeLance.setForeground(Color.white);
        ferDeLance.setBounds(x, y, largeurLabel, hauteurLabel);
        add(ferDeLance);

        x += largeurLabel;
        y = 70;

        boisButton = new VendreJToggleButton("Vendre");
        boisButton.setBounds(x, y, 85, hauteurLabel);
        boisButton.addActionListener(this);
        add(boisButton);

        y += espace + hauteurLabel;

        pierreButton = new VendreJToggleButton("Vendre");
        pierreButton.setBounds(x, y, 85, hauteurLabel);
        pierreButton.addActionListener(this);
        add(pierreButton);

        y += espace + hauteurLabel;

        poterieButton = new VendreJToggleButton("Vendre");
        poterieButton.setBounds(x, y, 85, hauteurLabel);
        poterieButton.addActionListener(this);
        add(poterieButton);

        y += espace + hauteurLabel;

        tissuButton = new VendreJToggleButton("Vendre");
        tissuButton.setBounds(x, y, 85, hauteurLabel);
        tissuButton.addActionListener(this);
        add(tissuButton);

        y += espace + hauteurLabel;

        ferDeLanceButton = new VendreJToggleButton("Vendre");
        ferDeLanceButton.setBounds(x, y, 85, hauteurLabel);
        ferDeLanceButton.addActionListener(this);
        add(ferDeLanceButton);

        y += espace + hauteurLabel * 2;

        // Développement Grenier
        x = largeur / 2 + 50;
        labelGrenier = new JLabel("Vendre de la nourriture");
        labelGrenier.setFont(GraphicsHelper.getFont(13, null));
        labelGrenier.setForeground(Color.white);
        labelGrenier.setBounds(x, y, 160, hauteurLabel);
        add(labelGrenier);

        nourritureMoins = new JButtonBase(("-"));
        nourritureMoins.addActionListener(this);
        nourritureMoins.setBounds(x + 160, y + 10, 25, 15);
        add(nourritureMoins);

        nourriturePlus = new JButtonBase(("+"));
        nourriturePlus.addActionListener(this);
        nourriturePlus.setBounds(x + 240, y + 10, 25, 15);
        add(nourriturePlus);

        nourritureGrenier = new JLabel("0");
        nourritureGrenier.setFont(GraphicsHelper.getFont(13, null));
        nourritureGrenier.setForeground(Color.white);
        nourritureGrenier.setBounds(x + 185, y, 55, hauteurLabel);
        nourritureGrenier.setHorizontalAlignment(SwingConstants.CENTER);
        add(nourritureGrenier);

        y += 50;

        img = GraphicsHelper.getImageIcon(GraphicsParameters.pathResPieceDeveloppement, this);
        label = new JLabel(img);
        label.setBounds(x, y, img.getIconWidth(), img.getIconHeight());
        add(label);

        x += img.getIconWidth() + 2 * espace;
        y += (img.getIconHeight() - hauteurLabel) / 2;

        label = new JLabel("Total : ");
        label.setFont(GraphicsHelper.getFont(13, null));
        label.setForeground(Color.white);
        label.setBounds(x, y, 50, hauteurLabel);
        add(label);

        x += 55;

        nbPieceTotal = new JLabel("0 pièce");
        nbPieceTotal.setFont(GraphicsHelper.getFont(13, null));
        nbPieceTotal.setForeground(Color.white);
        nbPieceTotal.setBounds(x, y, 70, hauteurLabel);
        nbPieceTotal.setHorizontalAlignment(SwingConstants.CENTER);
        add(nbPieceTotal);
    }

    public void reset() {
        descriptionText.setText("Description d'un developpement :  Choisir un developpement dans la liste ci-dessus.");

        // Liste des developpements possibles
        ArrayList<Developpement> listeDevPossible = controller.getlisteDeveloppementPossible();

        ArrayList<Developpement> listeDevTop = new ArrayList<Developpement>();
        ArrayList<Developpement> listeDevMid = new ArrayList<Developpement>();
        ArrayList<Developpement> listeDevLess = new ArrayList<Developpement>();

        for (Developpement dev : listeDevPossible) {
            if (listeDevJoueur == null || !listeDevJoueur.contains(dev)) {
                if (dev.getCout() < 16) {
                    listeDevLess.add(dev);
                } else if (dev.getCout() >= 16 && dev.getCout() <= 25) {
                    listeDevMid.add(dev);
                } else {
                    listeDevTop.add(dev);
                }
            }
        }

        listLess.setModel(new DeveloppementListModel(listeDevLess));
        listMid.setModel(new DeveloppementListModel(listeDevMid));
        listTop.setModel(new DeveloppementListModel(listeDevTop));

        listeRessourceSel = new ArrayList<Class>();
        boisButton.setSelected(false);
        pierreButton.setSelected(false);
        poterieButton.setSelected(false);
        tissuButton.setSelected(false);
        ferDeLanceButton.setSelected(false);

        selectedDeveloppement = null;

        // Développement grenier
        if (listeDevJoueur != null) {
            boolean trouve = false;
            for (Developpement dev : listeDevJoueur) {
                if (dev instanceof Grenier) {
                    trouve = true;
                    break;
                }
            }
            labelGrenier.setVisible(trouve);
            nourritureGrenier.setVisible(trouve);
            nourritureMoins.setVisible(trouve);
            nourriturePlus.setVisible(trouve);
            nourritureGrenier.setText("0");
        }

        nbPieceSel = nbPieceDispo;
        majTotalPiece();
    }

    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == etapeSuivante) {
            // Bouton étape suivante
            controller.etapeSuivante();
        } else if (e.getSource() instanceof VendreJToggleButton) {
            if (e.getSource() == boisButton) {
                if (boisButton.isSelected() && !listeRessourceSel.contains(Bois.class)) {
                    listeRessourceSel.add(Bois.class);
                    nbPieceSel += nbBois;
                } else if (!boisButton.isSelected()) {
                    listeRessourceSel.remove(Bois.class);
                    nbPieceSel -= nbBois;
                }
            } else if (e.getSource() == pierreButton) {
                if (pierreButton.isSelected() && !listeRessourceSel.contains(Pierre.class)) {
                    listeRessourceSel.add(Pierre.class);
                    nbPieceSel += nbPierre;
                } else if (!pierreButton.isSelected()) {
                    listeRessourceSel.remove(Pierre.class);
                    nbPieceSel -= nbPierre;
                }
            } else if (e.getSource() == poterieButton) {
                if (poterieButton.isSelected() && !listeRessourceSel.contains(Poterie.class)) {
                    listeRessourceSel.add(Poterie.class);
                    nbPieceSel += nbPoterie;
                } else if (!poterieButton.isSelected()) {
                    listeRessourceSel.remove(Poterie.class);
                    nbPieceSel -= nbPoterie;
                }
            } else if (e.getSource() == tissuButton) {
                if (tissuButton.isSelected() && !listeRessourceSel.contains(Tissu.class)) {
                    listeRessourceSel.add(Tissu.class);
                    nbPieceSel += nbTissu;
                } else if (!tissuButton.isSelected()) {
                    listeRessourceSel.remove(Tissu.class);
                    nbPieceSel -= nbTissu;
                }
            } else if (e.getSource() == ferDeLanceButton) {
                if (ferDeLanceButton.isSelected() && !listeRessourceSel.contains(FerDeLance.class)) {
                    listeRessourceSel.add(FerDeLance.class);
                    nbPieceSel += nbFerDeLance;
                } else if (!ferDeLanceButton.isSelected()) {
                    listeRessourceSel.remove(FerDeLance.class);
                    nbPieceSel -= nbFerDeLance;
                }
            }
            majTotalPiece();
        } else if (e.getSource() == nourritureMoins) {
            int valeur = Integer.parseInt(nourritureGrenier.getText());
            if (valeur > 0) {
                valeur--;
                nbPieceSel -= 6;
            }
            nourritureGrenier.setText(String.valueOf(valeur));
            majTotalPiece();
        } else if (e.getSource() == nourriturePlus) {
            int valeur = Integer.parseInt(nourritureGrenier.getText());
            if (valeur < nbNourritureDispo) {
                valeur++;
                nbPieceSel += 6;
            }
            nourritureGrenier.setText(String.valueOf(valeur));
            majTotalPiece();
        }
    }

    public void dragEnter(DragSourceDragEvent dsde) {
    }

    public void dragOver(DragSourceDragEvent dsde) {
    }

    public void dropActionChanged(DragSourceDragEvent dsde) {
    }

    public void dragExit(DragSourceEvent dse) {
    }

    public void dragDropEnd(DragSourceDropEvent dsde) {
    }

    public void dragGestureRecognized(DragGestureEvent dge) {
        transferable = null;
        if (dge.getComponent() == listLess) {
            transferable = new StringSelection(listLess.getSelectedValue().toString());
        } else if (dge.getComponent() == listMid) {
            transferable = new StringSelection(listMid.getSelectedValue().toString());
        } else if (dge.getComponent() == listTop) {
            transferable = new StringSelection(listTop.getSelectedValue().toString());
        }
        if (transferable != null) {
            try {
                ds.startDrag(dge, DragSource.DefaultCopyDrop, transferable, this);
            } catch (Exception e) {
            }
        }
    }

    @Override
    public void listeDeveloppementChanged(ArrayList<Developpement> listeDeveloppement) {
        listeDevJoueur = listeDeveloppement;
    }

    public void valueChanged(ListSelectionEvent e) {
        if (e.getSource() == listLess || e.getSource() == listMid || e.getSource() == listTop) {
            JList liste = (JList) e.getSource();
            int index = liste.getSelectedIndex();
            if (index != -1) {
                DeveloppementListModel listeModel = (DeveloppementListModel) liste.getModel();
                Developpement dev = listeModel.getDeveloppement(index);
                descriptionText.setText("Développement ");
                descriptionText.append(dev.getNom());
                descriptionText.append(", coût : ");
                descriptionText.append(String.valueOf(dev.getCout()));
                descriptionText.append(", points : ");
                descriptionText.append(String.valueOf(dev.getPoints()));
                descriptionText.append(".\n");
                descriptionText.append(dev.getEffet());
                descriptionText.setCaretPosition(0);

                selectedDeveloppement = dev;
            }
        }
    }

    @Override
    public void boisChanged(int nbBois) {
        bois.setText("Gains : " + nbBois + " pièce" + (nbBois > 1 ? "s" : ""));
        this.nbBois = nbBois;
    }

    @Override
    public void pierreChanged(int nbPierre) {
        pierre.setText("Gains : " + nbPierre + " pièce" + (nbPierre > 1 ? "s" : ""));
        this.nbPierre = nbPierre;
    }

    @Override
    public void poterieChanged(int nbPoterie) {
        poterie.setText("Gains : " + nbPoterie + " pièce" + (nbPoterie > 1 ? "s" : ""));
        this.nbPoterie = nbPoterie;
    }

    @Override
    public void tissuChanged(int nbTissu) {
        tissu.setText("Gains : " + nbTissu + " pièce" + (nbTissu > 1 ? "s" : ""));
        this.nbTissu = nbTissu;
    }

    @Override
    public void ferDeLanceChanged(int nbFerDeLance) {
        ferDeLance.setText("Gains : " + nbFerDeLance + " pièce" + (nbFerDeLance > 1 ? "s" : ""));
        this.nbFerDeLance = nbFerDeLance;
    }

    @Override
    public void nourritureChanged(int nbNourriture) {
        nbNourritureDispo = nbNourriture;
    }

    @Override
    public void pieceChanged(int nbPiece) {
        nbPieceDispo = nbPiece;
    }

    public void acheterDeveloppementSelectionne() {
        if (selectedDeveloppement != null) {

            if (controller.ajouterDeveloppementRealise(selectedDeveloppement, listeRessourceSel, Integer.parseInt(nourritureGrenier.getText()))) {
                controller.etapeSuivante();
            } else {
                JOptionPane.showMessageDialog(this, "Vous ne pouvez pas acheter ce développement.", "", JOptionPane.WARNING_MESSAGE);
            }
        }
    }

    public void majTotalPiece() {
        nbPieceTotal.setText(nbPieceSel + " pièce" + (nbPieceSel > 0 ? "s" : ""));
    }
}
